package ui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;


/**
 * This abstract class assembles the common elements across all forms, and
 * provides various other functions to interact with the system.
 * 
 * @author Aaron Chen
 * @version 3/6/2014
 */
@SuppressWarnings("serial")
public abstract class AbstractForm extends AbstractMainComponent {
  
  /** The maximum rating that can be given in a radio button type rating question. */
  protected static final int MAXIMUM_RATING = 5;
  
  /** The panel mode that allows the user to fill in a new form. */
  protected static final boolean MODE_NEW_FORM = false;
  
  /** The panel mode that allows the user to view a previously filled form and
   * possibly allows for editing. */
  protected static final boolean MODE_EXISTING_FORM = true;
  
  /** The submission button. */
  protected JButton my_btn_submit;
  
  /** The edit button. */
  protected JButton my_btn_save_changes;
  
//  /** The mode of the panel.  True turns the panel into a display for an existing
//   * form that may be editable, while false turns the panel into a blank form. */
//  private boolean my_mode;
  

  /**
   * Create the internal frame, which acts as a panel.
   * @param the_parent The main window.
   */
  public AbstractForm(final DisplayPanel the_parent) {
    super(the_parent);
    setFrameParameters();
    final JPanel main_panel = createMainPanel();
//    getContentPane().add(main_panel);
    add(main_panel);
    
//    pack();
//    setResizable(false);
    setVisible(true);
  }

  /**
   * Sets up the internal frame's properties.
   */
  protected void setFrameParameters() {
    setBackground(Standards.COLOR_BACKGROUND);
    setBorder(null);
//    final javax.swing.plaf.InternalFrameUI ifu = getUI();
//    ((javax.swing.plaf.basic.BasicInternalFrameUI) ifu).setNorthPane(null);  
    setBorder(null);
//    getContentPane().setLayout(new FlowLayout());
    setFocusable(true);
  }
  
  /**
   * Creates the main panel, which will house the entire form.
   * @return The main panel.
   */
  protected JPanel createMainPanel() {
    final JPanel panel_main = new JPanel();
    panel_main.setBorder(null);
    panel_main.setBackground(Standards.COLOR_BACKGROUND);
    panel_main.setLayout(new BoxLayout(panel_main, BoxLayout.Y_AXIS));

    panel_main.add(createTitleLabelPanel());
    panel_main.add(Box.createVerticalStrut(Standards.STRUT_LENGTH_MEDIUM));
    panel_main.add(createFormPanel());
    panel_main.add(Box.createVerticalStrut(Standards.STRUT_LENGTH_MEDIUM));
    panel_main.add(createButtonsPanel());
    
    return panel_main;
  }
  /**
   * Creates the title panel for the top of the form.
   * @return The title panel.
   */
  protected JPanel createTitleLabelPanel() {
    final JPanel panel_title = new JPanel();
    panel_title.setBorder(Standards.BORDER_COMPOUND_FORM);
    panel_title.setBackground(Standards.COLOR_BACKGROUND);
    
    final JLabel lbl_title = new JLabel(getFormTitle());
    lbl_title.setHorizontalAlignment(SwingConstants.CENTER);
    lbl_title.setFont(Standards.FONT_TITLE);
    lbl_title.setAlignmentX(Component.CENTER_ALIGNMENT);

    panel_title.add(lbl_title);
    
    return panel_title;
  }
  
  /**
   * Gets the title of the form.
   * @return The form title String.
   */
  protected abstract String getFormTitle();
  
  /**
   * Creates the form panel, which holds all of the input fields.
   * @return The form panel.
   */
  protected abstract JPanel createFormPanel();
  
  /**
   * Creates the buttons panel, which holds the buttons at the bottom of the
   * form.
   * @return The buttons panel.
   */
  protected JPanel createButtonsPanel() {
    final JPanel panel_buttons = new JPanel();
    panel_buttons.setBackground(Standards.COLOR_BACKGROUND);
    panel_buttons.setAlignmentX(Component.LEFT_ALIGNMENT);
    
    
    my_btn_submit = new JButton("Submit");
    
    my_btn_save_changes = new JButton("Save Changes");
    my_btn_save_changes.setVisible(false);
    
    final JButton btn_cancel = new JButton("Cancel");
    btn_cancel.addActionListener(new ActionListener() {
      /** The action to be performed.
       * Removes the form from view. */
      @Override
      public void actionPerformed(final ActionEvent the_e) {
        getDisplayStack().removeFromStack();
      }
    });
    
    panel_buttons.add(my_btn_submit);
    panel_buttons.add(my_btn_save_changes);
    panel_buttons.add(btn_cancel);
    
    return panel_buttons;
  }
  
  /**
   * Creates a scroll pane that shows a vertical scroll bar and suppresses
   * the horizontal scroll bar.
   * @param the_view The component to be placed within the scroll pane.
   * @return The scroll pane with the component inside.
   */
  protected JScrollPane createScrollPane(final Component the_view) {
    final JScrollPane scroll_pane = new JScrollPane(the_view);
    scroll_pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    scroll_pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    return scroll_pane;
  }
  
  /**
   * Creates a group of radio buttons used to rate a category.
   * @param the_str The label of the category.
   * @param the_group The button group for the radio buttons to be added in.
   * @return The panel that contains the radio buttons.
   */
  protected JPanel createRadioButtonQuestion(final String the_str,
                                             final ButtonGroup the_group) {
    final JPanel panel_radio = new JPanel();
    panel_radio.setBackground(Standards.COLOR_BACKGROUND);
    panel_radio.setLayout(new BorderLayout(0, 0));
    
    final JTextArea ta = new JTextArea(the_str);
    ta.setBackground(SystemColor.activeCaption);
    ta.setEditable(false);
    ta.setFont(Standards.FONT_BOLD);
    ta.setWrapStyleWord(true);
    ta.setLineWrap(true);
    ta.setRows(ta.getLineCount());
    panel_radio.add(ta, BorderLayout.CENTER);
    
    final JPanel panel = new JPanel();
    panel.setBackground(Standards.COLOR_BACKGROUND);
    panel_radio.add(panel, BorderLayout.SOUTH);
    
    final JRadioButton rdbtn_strongly_accepted = new JRadioButton("5 - Strongly Accepted");
    rdbtn_strongly_accepted.setFont(Standards.FONT_STANDARD);
    rdbtn_strongly_accepted.setBackground(Standards.COLOR_BACKGROUND);
    
    final JRadioButton rdbtn_accepted = new JRadioButton("4 - Accepted");
    rdbtn_accepted.setFont(Standards.FONT_STANDARD);
    rdbtn_accepted.setBackground(Standards.COLOR_BACKGROUND);
    
    final JRadioButton rdbtn_neutral = new JRadioButton("3 - Neutral");
    rdbtn_neutral.setFont(Standards.FONT_STANDARD);
    rdbtn_neutral.setBackground(Standards.COLOR_BACKGROUND);
    
    final JRadioButton rdbtn_rejected = new JRadioButton("2 - Rejected");
    rdbtn_rejected.setFont(Standards.FONT_STANDARD);
    rdbtn_rejected.setBackground(Standards.COLOR_BACKGROUND);
    
    final JRadioButton rdbtn_strongly_rejected = new JRadioButton("1 - Strongly Rejected");
    rdbtn_strongly_rejected.setFont(Standards.FONT_STANDARD);
    rdbtn_strongly_rejected.setBackground(Standards.COLOR_BACKGROUND);
    
    the_group.add(rdbtn_strongly_accepted);
    the_group.add(rdbtn_accepted);
    the_group.add(rdbtn_neutral);
    the_group.add(rdbtn_rejected);
    the_group.add(rdbtn_strongly_rejected);

    panel.add(rdbtn_strongly_accepted);
    panel.add(rdbtn_accepted);
    panel.add(rdbtn_neutral);
    panel.add(rdbtn_rejected);
    panel.add(rdbtn_strongly_rejected);
    
    return panel_radio;
  }
  
  /**
   * Sets a radio button within a button group to be selected. 
   * @param the_group The button group.
   * @param the_n     The radio button to be selected.
   */
  protected void setRadioButtonInGroup(final ButtonGroup the_group, final int the_n) {
    final Enumeration<AbstractButton> enumeration = the_group.getElements();
    for (int i = 0; i < MAXIMUM_RATING && enumeration.hasMoreElements(); i++) {
      final AbstractButton button = enumeration.nextElement();
      if (Standards.RATING_MAX_SELECTION - i == the_n) {
        button.setSelected(true);
        break;
      }
    }
  }
  
  /**
   * Gets the index of the button that was selected in the button group.
   * @param the_group The button group.
   * @return The 1-based index of the button that is selected, or -1 if
   *         no button is selected.
   */
  protected int getRadioButtonIndexInGroup(final ButtonGroup the_group) {
    int result = -1;
    final Enumeration<AbstractButton> enumeration = the_group.getElements();
    for (int i = 0; i < MAXIMUM_RATING && enumeration.hasMoreElements(); i++) {
      final AbstractButton button = enumeration.nextElement();
      if (button.isSelected()) {
        result = Standards.RATING_MAX_SELECTION - i;
        break;
      }
    }
    return result;
  }
  
  /**
   * Determines the mode of the panel.
   * @param the_bool True if the panel is set to allow the view of a
   * previously filled form; false for filling out a new form.
   */
  protected void setMode(final boolean the_bool) {
    if (my_btn_submit != null && my_btn_save_changes != null) {
      my_btn_submit.setVisible(!the_bool);
      my_btn_save_changes.setVisible(the_bool);
    }
  }
  
}
